package com.vonchange.headb.utils.orm;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.vonchange.headb.core.base.HeaCore;
import com.vonchange.headb.core.bean.Entity;
import com.vonchange.headb.core.bean.EntityField;
import com.vonchange.headb.core.bean.Join;
import com.vonchange.headb.core.bean.SelectColumn;
import com.vonchange.headb.core.constant.HeaConstant;
import com.vonchange.headb.utils.config.HConfigUtil;
import com.vonchange.headb.utils.logger.HLogUtils;
import com.vonchange.headb.utils.map.HHashMap;
import com.vonchange.headb.utils.orm.impl.OrmImpl;
import com.vonchange.headb.utils.orm.impl.OrmImplNot;
import com.vonchange.headb.utils.string.HStringUtils;
import com.vonchange.headb.utils.string.third.StringUtils;
import com.vonchange.headb.utils.xml.HXmlUtils;

/**
 * Orm组件
 * 
 * @author von_change@163.com
 * @date 2015-6-14 下午1:02:52
 */
public class HOrmUtil {
	private static final Log logger = LogFactory.getLog(HOrmUtil.class);
	/**
	 * _转大写
	 * 
	 * @param value
	 */
	public static String toUp(String value) {
		StringBuffer sb = new StringBuffer();
		boolean flag = false;
		for (int i = 0; i < value.length(); i++) {
			char cur = value.charAt(i);
			if (cur == '_') {
				flag = true;

			} else {
				if (flag) {
					sb.append(Character.toUpperCase(cur));
					flag = false;
				} else {
					sb.append(cur);
				}
			}
		}
		return sb.toString();
	}

	private static boolean getSqlIsOrm() {
		File xmlPath = HConfigUtil.getConfigXmlFile();
		if(null==xmlPath){
			return true;
		}
		HXmlUtils xmlUtils = new HXmlUtils(xmlPath);
		return xmlUtils.sqlIsOrm();
	}

	private static IOrm getOrm() {
		boolean flag = getSqlIsOrm();
		if (flag) {
			return new OrmImpl();
		}
		if (!flag) {
			return new OrmImplNot();
		}
		return new OrmImpl();
	}

	/**
	 * 数据库字段名转实体类字段名
	 * 
	 * @param colName
	 * @return 实体类字段名
	 */
	public static String toFiled(String colName) {
		IOrm orm = getOrm();
		return orm.toFiled(colName);
	}

	/**
	 * Hql转成sql
	 * 
	 * @param myHql
	 * @return sql
	 */
	public static String toSql(String myHql) {
		IOrm orm = getOrm();
		return orm.toSql(myHql);
	}

	/**
	 * 数据库表名转实体名
	 * 
	 * @param tableName
	 * @return 实体名
	 */
	public static String toEntity(String tableName) {
		StringBuffer sb = new StringBuffer();
		boolean flag = false;
		for (int i = 0; i < tableName.length(); i++) {
			char cur = tableName.charAt(i);
			if (cur == '_') {
				flag = true;

			} else {
				if (flag) {
					sb.append(Character.toUpperCase(cur));
					flag = false;
				} else {
					sb.append(Character.toLowerCase(cur));
					//sb.append(cur);
				}

			}
		}
		return HStringUtils.capitalize(sb.toString());
	}
	/**
	 * 从sql语句中获得alias
	 * 
	 * @param sqlFragment
	 * @return Map
	 */
	public static Map<String, Boolean> getAliasFromSql(String sqlFragment) {
		Map<String, Boolean> aliasMap = new HHashMap<String, Boolean>();
		Matcher m = Pattern.compile("([\\w]*\\.[\\w]*)").matcher(sqlFragment);
		while (m.find()) {
			String group = m.group();
			if (!group.startsWith("t.")) {
				String aliasStr = HStringUtils.substringBefore(group, ".");
				aliasStr=aliasStr.replaceAll("@", "");
				aliasMap.put(aliasStr, false);
			}
		}
		return aliasMap;
	}

	/**
	 * 分析查询字段语句
	 * 
	 * @param columnStr
	 * @return SelectColumn
	 */
	public static SelectColumn analyzeSelectColumn(String columnStr,HXmlUtils xmlUtils) {
		SelectColumn selectColumn = new SelectColumn();
		selectColumn.setOrgColumnSql(columnStr);
		HHashMap<String, Boolean> aliasMap = new HHashMap<String, Boolean>();
		Matcher mas = Pattern.compile("(as[ ]*[\\w]*\\.[\\w]*)").matcher(columnStr);
		while (mas.find()) {
			String group = mas.group();
			String repalceStr = group.replace(".", HeaConstant.DIANINALIAS);
			if (!repalceStr.equals(group)) {
				columnStr = columnStr.replace(group, repalceStr);
			}
		}
		Matcher m = Pattern.compile("([\\@\\w]*\\.[\\w\\*]*)").matcher(columnStr);
		List<String> patternListW = new ArrayList<String>();
		List<String> replaceStrListW = new ArrayList<String>();
		while (m.find()) {
			String group = m.group();
			StringBuffer repalceStr = new StringBuffer();
			if (!group.startsWith("t.")) {
				//.*
				if(group.endsWith(".*")){	
					//需要重构 一次性加载bean对象属性到map
					//String allCoumnStr=getAllCoulmnStr(group,xmlUtils);
					//patternListW.add(group);
					//replaceStrListW.add(allCoumnStr);
				}else{
					String aliasStr = HStringUtils.substringBefore(group, ".");
					aliasStr=aliasStr.replaceAll("@", "");
					aliasMap.set(aliasStr, false);
					String alias = group.replace(".", HeaConstant.DIANINALIAS);
					repalceStr.append(group).append(" as ").append(alias);
					if (group.startsWith("@")) {
						repalceStr = new StringBuffer();
						repalceStr.append(group.substring(1));
					}
					patternListW.add(group);
					replaceStrListW.add(repalceStr.toString());
				}	
			}
		}
		columnStr = HStringUtils.replaceEach(columnStr, patternListW.toArray(new String[patternListW.size()]), replaceStrListW.toArray(new String[replaceStrListW.size()]));
		selectColumn.setCookedColumnSql(columnStr);
		selectColumn.setAliasMap(aliasMap);
		logger.debug(HLogUtils.format("字段sql", columnStr));
		return selectColumn;
	}
	private static String  getAllCoulmnStr(String group,HXmlUtils xmlUtils){
		String alias=StringUtils.substringBefore(group, ".");
		Map<String, Entity> entityMap=	HeaCore.entityMap;
		Join join = xmlUtils.getJoin(alias);
		String entityName=StringUtils.substringAfterLast(join.getClasspath(),".");
		Entity entity =entityMap.get(entityName);
		Map<String,EntityField> filedMap=	entity.getFieldMap();
		StringBuffer sb= new StringBuffer();
		for (Entry<String, EntityField> entry : filedMap.entrySet()) {
			EntityField field=entry.getValue();
			sb.append(" ").append(alias).append(".").append(field.getColumnName()).append(" as ")
			.append("_").append(field.getFieldName());
		}
		return sb.toString();
	}

}
